`timescale 1ns / 1ps
/////////////////////////////////////////////////////////////////////////////
////                                                                     ////
//// Instituto Tecnologico de Costa Rica                                 ////
////                                                                     ////
//// Maquina estados finitos                                             ////
////                                                                     ////
//// Este archivo es parte del proyecto: Control de luces de semaforo    ////
//// http://repositorio-charmander.googlecode.com/svn/trunk/             ////
////                                                                     ////
//// Descripcion                                                         ////
//// Implementacion de un control de luces de semaforo como un proyecto  ////
//// del curso de Taller de Diseño Logico.                               ////
////                                                                     ////
//// Funcionamiento:                                                     ////
//// - Maquina de estados del Controlador  de Luces. En este modulo es   ////
////   donde se procesan y se da la toma de decisiones por parte del     ////
////   programa para saber a que estado debera pasar segun las valores   ////
////   que ingresen.                                                     ////
////                                                                     ////
////                                                                     ////                                    
//// Autores:                                                            ////
//// - Gia Chen, kathya0812@gmail.com                                    ////
////   Edgar Rojas, edtec217@gmail.com                                   ////
////                                                                     ////
/////////////////////////////////////////////////////////////////////////////

module MaquinaEstadosFinitos( _clk_i, sensor_sync_i, Walk_Request_i, prog_sync_i, expired_i, _sync_rst_i,
										Rm_o, Ym_o, Gm_o, Rs_o, Ys_o, Gs_o, walk_o, start_timer_o, interval_o, _WR_rst_o);
	//ENTRADAS
	//Clock
	input _clk_i;
	//Señales de distintos módulos
	input sensor_sync_i; //Sincronizador
	input Walk_Request_i; //WalkRegister
	input prog_sync_i; //Sincronizador
	input expired_i; //Timer
	//RESET
	input _sync_rst_i;
	
	//SALIDAS
	//Luces del semáforo
	output reg Rm_o, Ym_o, Gm_o, Rs_o, Ys_o, Gs_o, walk_o;
	//Señales a distintos módulos
	output reg start_timer_o; //Timer
	output reg[1:0] interval_o; //Timer
	output reg _WR_rst_o; //WalkRegister
	
	//WIRES
	reg[3:0] estado_actual;

	//Primero se evalúa si la señal de reset o la de reprogram
   //ya que de ser así, se reiniciará el contador de la FSM.
	//Luego se evaluará el estado en el que se encuentra la FSM
	//y, depende del valor que tengan las entradas en ese momento,
	//se tomarán las decisiones de hacia cúal estado se deberá
	//cambiar y cuales variables se deberán activar.
	always @(posedge _clk_i)
		begin
			if(prog_sync_i || _sync_rst_i)
				begin
					estado_actual <= 0;
					start_timer_o <= 1;
				end
			else
				begin
					if(expired_i)
						begin
							start_timer_o <= 0;
						end
				
				case(estado_actual)
					//ESTADO 0
					4'd0:
						begin
							Rm_o <= 1;
							Ym_o <= 1;
							Gm_o <= 0;
							Rs_o <= 0;
							Ys_o <= 1;
							Gs_o <= 1;
							walk_o <= 1;
							start_timer_o <= start_timer_o;
							interval_o <= 0;
							_WR_rst_o <= 0;
							
							if(expired_i)
								begin
									estado_actual <= 1;
									start_timer_o <= 1;
								end
						end
						
					//ESTADO 1
					4'd1:
						begin
							Rm_o <= 1;
							Ym_o <= 1;
							Gm_o <= 0;
							Rs_o <= 0;
							Ys_o <= 1;
							Gs_o <= 1;
							walk_o <= 1;
							start_timer_o <= start_timer_o;
							interval_o <= 0;
							_WR_rst_o <= 0;
							
							if(sensor_sync_i)
								begin
									estado_actual <= 2;
									start_timer_o <= 1;
								end
							else
								begin
									estado_actual <= 3;
									start_timer_o <= 1;
								end
						end
					//ESTADO 2
					4'd2:
						begin
							Rm_o <= 1;
							Ym_o <= 1;
							Gm_o <= 0;
							Rs_o <= 0;
							Ys_o <= 1;
							Gs_o <= 1;
							walk_o <= 1;
							start_timer_o <= start_timer_o;
							interval_o <= 1;
							_WR_rst_o <= 0;
							
							if(expired_i)
								begin
									estado_actual <= 4;
									start_timer_o <= 1;
								end
						end
						
					//ESTADO 3
					4'd3:
						begin
							Rm_o <= 1;
							Ym_o <= 1;
							Gm_o <= 0;
							Rs_o <= 0;
							Ys_o <= 1;
							Gs_o <= 1;
							walk_o <= 1;
							start_timer_o <= start_timer_o;
							interval_o <= 0;
							_WR_rst_o <= 0;
							
							if(expired_i)
								begin
									estado_actual <= 4;
									start_timer_o <= 1;
								end
						end
						
					//ESTADO 4
					4'd4:
						begin
							Rm_o <= 1;
							Ym_o <= 0;
							Gm_o <= 1;
							Rs_o <= 0;
							Ys_o <= 1;
							Gs_o <= 1;
							walk_o <= 1;
							start_timer_o <= start_timer_o;
							interval_o <= 2;
							_WR_rst_o <= 0;
							
							if(expired_i)
								begin
									estado_actual <= 5;
									start_timer_o <= 1;
								end
						end
						
					//ESTADO 5
					4'd5:
						begin
							Rm_o <= 1;
							Ym_o <= 0;
							Gm_o <= 1;
							Rs_o <= 0;
							Ys_o <= 1;
							Gs_o <= 1;
							walk_o <= 1;
							start_timer_o <= start_timer_o;
							interval_o <= 2;
							_WR_rst_o <= 0;
							
							if(Walk_Request_i)
								begin
									estado_actual <= 6;
									start_timer_o <= 1;
								end
							else
								begin
									estado_actual <= 7;
									start_timer_o <= 1;
								end
						end
						
					//ESTADO 6
					4'd6:
						begin
							Rm_o <= 0;
							Ym_o <= 1;
							Gm_o <= 1;
							Rs_o <= 0;
							Ys_o <= 1;
							Gs_o <= 1;
							walk_o <= 0;
							start_timer_o <= start_timer_o;
							interval_o <= 1;
							_WR_rst_o <= 0;
							
							if(expired_i)
								begin
									estado_actual <= 7;
									start_timer_o <= 1;
								end
						end
						
					//ESTADO 7
					4'd7:
						begin
							Rm_o <= 0;
							Ym_o <= 1;
							Gm_o <= 1;
							Rs_o <= 1;
							Ys_o <= 1;
							Gs_o <= 0;
							walk_o <= 1;
							start_timer_o <= start_timer_o;
							interval_o <= 0;
							_WR_rst_o <= 1;
							
							if(expired_i)
								begin
									estado_actual <= 8;
									start_timer_o <= 1;
								end
						end
						
					//ESTADO 8
					4'd8:
						begin
							Rm_o <= 0;
							Ym_o <= 1;
							Gm_o <= 1;
							Rs_o <= 1;
							Ys_o <= 1;
							Gs_o <= 0;
							walk_o <= 1;
							start_timer_o <= start_timer_o;
							interval_o <= 0;
							_WR_rst_o <= 0;
							
							if(sensor_sync_i)
								begin
									estado_actual <= 9;
									start_timer_o <= 1;
								end
							else
								begin
									estado_actual <= 10;
									start_timer_o <= 1;
								end
						end
						
					//ESTADO 9
					4'd9:
						begin
							Rm_o <= 0;
							Ym_o <= 1;
							Gm_o <= 1;
							Rs_o <= 1;
							Ys_o <= 1;
							Gs_o <= 0;
							walk_o <= 1;
							start_timer_o <= start_timer_o;
							interval_o <= 2;
							_WR_rst_o <= 0;
							
							if(expired_i)
								begin
									estado_actual <= 10;
									start_timer_o <= 1;
								end
						end
					
					//ESTADO 10
					4'd10:
						begin
							Rm_o <= 0;
							Ym_o <= 1;
							Gm_o <= 1;
							Rs_o <= 1;
							Ys_o <= 0;
							Gs_o <= 1;
							walk_o <= 1;
							start_timer_o <= start_timer_o;
							interval_o <= 2;
							_WR_rst_o <= 0;
							
							if(expired_i)
								begin
									estado_actual <= 0;
									start_timer_o <= 1;
								end
						end
						
					default 
						begin
							Rm_o <= 1;
							Ym_o <= 1; 
							Gm_o <= 0;
							Rs_o <= 0;
							Ys_o <= 1;
							Gs_o <= 1;
							walk_o <= 1;
							start_timer_o <= start_timer_o;
							interval_o <= 0;
							_WR_rst_o <= 0;

							estado_actual <= 0;
							start_timer_o <= 1;
						end
				endcase
			end
		end
endmodule
